package com.atguigu.tingshu.album.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.mapper.*;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.cache.GuiGuCache;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.user.client.UserFeignClient;

import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.concurrent.ConcurrentUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

	@Autowired
	private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private BaseCategoryViewMapper baseCategoryViewMapper;

	@Autowired
	private AlbumAttributeValueMapper albumAttributeValueMapper;

	@Autowired
	private UserFeignClient userFeignClient;

	@Autowired
	private AlbumStatMapper albumStatMapper;

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private RabbitService rabbitService;


	@Override
	public List<JSONObject> getBaseCategoryList() {

		List<JSONObject> jsonObjectList = new ArrayList<>();

		//先查找全部
		List<BaseCategoryView> baseCategoryViewList = baseCategoryViewMapper.selectList(null);

		if(CollectionUtils.isEmpty(baseCategoryViewList)){
			throw  new GuiguException(400,"用户数据为空");
		}

		//将结果分组
		Map<Long, List<BaseCategoryView>> map = baseCategoryViewList.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory1Id));

		for (Map.Entry<Long, List<BaseCategoryView>> baseCategoryView : map.entrySet()) {
			//获取一级分类
			JSONObject jsonObject1 = new JSONObject();
			Long key = baseCategoryView.getKey();
			List<BaseCategoryView> categoryViewValue = baseCategoryView.getValue();
			jsonObject1.put("categoryId",key);
			jsonObject1.put("categoryName",categoryViewValue.get(0).getCategory1Name());

			//baseCategoryView 二级分类下的信息的map value才是
			List<JSONObject> jsonObjectList2 = new ArrayList<>();
			List<BaseCategoryView> baseCategoryView2 = baseCategoryView.getValue();
			Map<Long, List<BaseCategoryView>> map2 = baseCategoryView2.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
			for (Map.Entry<Long, List<BaseCategoryView>> longListEntry : map2.entrySet()) {
				JSONObject jsonObject = new JSONObject();
				Long key1 = longListEntry.getKey();
				String category2Name = longListEntry.getValue().get(0).getCategory2Name();
				jsonObject.put("categoryId",key1);
				jsonObject.put("categoryName",category2Name);

				//三级分类的信息集合map
				List<BaseCategoryView> baseCategoryView3 = longListEntry.getValue();
				ArrayList<JSONObject> jsonObjectList3 = new ArrayList<>();
				for (BaseCategoryView categoryView : baseCategoryView3) {
					Long key3 = categoryView.getCategory3Id();
					String category3Name = categoryView.getCategory3Name();
					JSONObject jsonObject3 = new JSONObject();
					jsonObject3.put("categoryName",category3Name);
					jsonObject3.put("categoryId",key3);
					//三级分类
					jsonObjectList3.add(jsonObject3);
				}
				//二级分类  将三级分类放进去
				jsonObject.put("categoryChild",jsonObjectList3);
				jsonObjectList2.add(jsonObject);

			}
			jsonObject1.put("categoryChild",jsonObjectList2);
			//一级分类 将二级分类放入到一级分类
			jsonObjectList.add(jsonObject1);


		}

		return jsonObjectList;
	}

	/**
	 * 保存专辑
	 * @param albumInfoVo
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveAlbumInfo(AlbumInfoVo albumInfoVo) {

		//获取登陆者的id
		Long userId = AuthContextHolder.getUserId();
		AlbumInfo albumInfo = new AlbumInfo();
		BeanUtils.copyProperties(albumInfoVo,albumInfo);
		albumInfo.setUserId(userId);
		albumInfo.setIsFinished("0");
		albumInfo.setEstimatedTrackCount(5);
		albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS);
		albumInfo.setIncludeTrackCount(0);
		//保存专辑信息
		albumInfoMapper.insert(albumInfo);

		//保存专辑属性值
		//id回显
		Long albumInfoId = albumInfo.getId();

		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
			AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
			albumAttributeValue.setAlbumId(albumInfoId);
			//属性拷贝
			BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
			albumAttributeValueMapper.insert(albumAttributeValue);
		}

		//保存专辑统计表
		this.saveAlbumStat( albumInfoId,SystemConstant.ALBUM_STAT_PLAY,0  );
		this.saveAlbumStat( albumInfoId,SystemConstant.ALBUM_STAT_SUBSCRIBE,0  );
		this.saveAlbumStat( albumInfoId,SystemConstant.ALBUM_STAT_BUY,0  );
		this.saveAlbumStat( albumInfoId,SystemConstant.ALBUM_STAT_COMMENT,0  );


		//调用rabbit发送上架专辑到索引库里面
		if("1".equals(albumInfoVo.getIsOpen())){
			//开发 发送消息
			rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.QUEUE_ALBUM_UPPER,albumInfoId.toString());
		}

	}


	/**
	 * 根据当前用户查询专辑分页信息
	 * @param page1 分页信息
	 * @param albumInfoQuery 用户信息和条件
	 * @return
	 */
	@Override
	public Page<AlbumListVo> findUserAlbumPage(Page page1, AlbumInfoQuery albumInfoQuery) {


		return albumInfoMapper.findUserAlbumPage(page1,albumInfoQuery);
	}


	/**
	 * 根据id删除专辑
	 * @param id
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeAlbumInfo(Long alnumId) {
		//如果专辑下有声音不能删除
		AlbumInfo albumInfo = albumInfoMapper.selectById(alnumId);
		if(albumInfo.getIncludeTrackCount().intValue() !=0){
			throw  new GuiguException(400,"专辑下有声音 不能删除");
		}

		//先删除基本信息
		albumInfoMapper.deleteById(alnumId);
		//2.删除属性关系表
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,alnumId));
		//3.专辑统计表
		albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId,alnumId));

		rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.QUEUE_ALBUM_LOWER,alnumId.toString());

	}


	/**
	 * 根据id回显数据
	 * @param id
	 */
	@Override
	@GuiGuCache(prefix = RedisConstant.ALBUM_INFO_PREFIX)
	public AlbumInfo getAlbumInfo(Long id) {

		AlbumInfo albumInfo = new AlbumInfo();

		albumInfo = albumInfoMapper.selectById(id);
		if(albumInfo!=null){
			//专辑属性值关系
			List<AlbumAttributeValue> albumAttributeValueList1 = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, id));
			albumInfo.setAlbumAttributeValueVoList(albumAttributeValueList1);
		}


		return albumInfo;

	}


	/**
	 * 修改专辑
	 * @param id 专辑id
	 * @param albumInfoVo 修改的信息
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateAlbumInfo(Long id, AlbumInfoVo albumInfoVo) {

		AlbumInfo albumInfoBeffer = albumInfoMapper.selectById(id);

		//1.先修改基础表
		AlbumInfo albumInfo = new AlbumInfo();
	    BeanUtils.copyProperties(albumInfoVo,albumInfo);
		albumInfo.setId(id);
		albumInfoMapper.updateById(albumInfo);
		//2. TODO 修改专辑属性表  多对多数据的修改 会只更改最后一个 需要先删除 在新增
		albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId,id));

		//3.新增
		List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
		for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
			AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
			albumAttributeValue.setAlbumId(id);
			//属性拷贝
			BeanUtils.copyProperties(albumAttributeValueVo,albumAttributeValue);
			albumAttributeValueMapper.insert(albumAttributeValue);
		}

		if(!albumInfoBeffer.getIsOpen().equals(albumInfoVo.getIsOpen())){
			//有修改公布
			if("1".equals(albumInfoVo.getIsOpen())){
				rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.QUEUE_ALBUM_UPPER,id.toString());
			}else if("0".equals(albumInfoVo.getIsOpen())) {
				//下架
				rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.QUEUE_ALBUM_LOWER,id.toString());
			}
		}
	}


	/**
	 * 根据当前用户查询全部专辑列表
	 * @param userId
	 */
	@Override
	public List<AlbumInfo> findUserAllAlbumList(Long userId) {
		AlbumInfo albumInfo = new AlbumInfo();
		albumInfo.setUserId(userId);
		List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(new LambdaQueryWrapper<AlbumInfo>()
				.eq(AlbumInfo::getUserId, userId)
				//数据太多 排序显示
				.orderByDesc(AlbumInfo::getId)
				.last("limit 100"));
		//填充数据
		for (AlbumInfo albumInfo1 : albumInfoList) {

			List<AlbumAttributeValue> albumAttributeValueList = albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>()
					.eq(AlbumAttributeValue::getAlbumId, albumInfo.getId())
					.orderByDesc(AlbumAttributeValue::getId)
					.last("limit 100"));
			albumInfo1.setAlbumAttributeValueVoList(albumAttributeValueList);

		}

		return albumInfoList;
	}


	/**
	 * albumInfoService
	 * @param category1Id 一级分类
	 * @return
	 */
	@Override
	public List<BaseCategory3> getTop7BaseCategory3(Long category1Id) {

		return albumInfoMapper.selectBaseCategory3(category1Id);
	}


	/**
	 * 根据一级分类id获取全部分类信息
	 * @param category1Id 一级分类
	 * @return
	 */
	@Override
	public JSONObject getBaseCategoryList002(Long category1Id) {
		//1.根据1级分类ID查询分类视图得到一级分类列表
		LambdaQueryWrapper<BaseCategoryView> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseCategoryView::getCategory1Id, category1Id);
		List<BaseCategoryView> baseCategory1List = baseCategoryViewMapper.selectList(queryWrapper);
		//2.处理一级分类对象 封装一级分类对象包含ID，分类名称
		if (CollectionUtil.isNotEmpty(baseCategory1List)) {
			//2.1 构建一级分类对象 封装ID，名称
			JSONObject jsonObject1 = new JSONObject();
			jsonObject1.put("categoryId", baseCategory1List.get(0).getCategory1Id());
			jsonObject1.put("categoryName", baseCategory1List.get(0).getCategory1Name());
			//3.处理一级分类下二级分类
			//3.1 将一级分类集合再按照二级分类ID分组得到Map Map中key:二级分类ID，Map中Value二级分类集合
			Map<Long, List<BaseCategoryView>> category2Map = baseCategory1List.stream().collect(Collectors.groupingBy(BaseCategoryView::getCategory2Id));
			//3.2 遍历Map每遍历一次Map封装二级分类JSON对象
			List<JSONObject> jsonObject2List = new ArrayList<>();
			for (Map.Entry<Long, List<BaseCategoryView>> entry2 : category2Map.entrySet()) {
				//3.3 构建二级分类对象，封装二级分类ID及名称
				JSONObject jsonObject2 = new JSONObject();
				jsonObject2.put("categoryId", entry2.getKey());
				jsonObject2.put("categoryName", entry2.getValue().get(0).getCategory2Name());
				jsonObject2List.add(jsonObject2);
				//4.处理二级分类下三级分类
				//4.1 遍历二级分类列表，没遍历一条记录构建三级分类对象
				List<JSONObject> jsonObject3List = new ArrayList<>();
				for (BaseCategoryView baseCategoryView : entry2.getValue()) {
					//4.2 构建三级分类对象，封装三级分类ID名称
					JSONObject jsonObject3 = new JSONObject();
					jsonObject3.put("categoryId", baseCategoryView.getCategory3Id());
					jsonObject3.put("categoryName", baseCategoryView.getCategory3Name());
					jsonObject3List.add(jsonObject3);
				}
				//4.3 将三级分类集合放入二级分类对象中
				jsonObject2.put("categoryChild", jsonObject3List);
			}
			//3.3 将二级分类集合放入一级分类对象中
			jsonObject1.put("categoryChild", jsonObject2List);
			return jsonObject1;
		}
		return null;
	}

	/**
	 * 根据专辑ID获取专辑统计信息
	 * @param albumId
	 * @return
	 */
	@Override
	@GuiGuCache(prefix = "albumStatVo:")
	public AlbumStatVo getAlbumStatVo(Long albumId) {
	     AlbumStatVo albumStatVo =	albumStatMapper.selectAlbumStatVo(albumId);
		return albumStatVo;
	}


	/**
	 * 查询专辑声音分页列表
	 * @param albumId 专辑id
	 * @param userId 用户id
	 * @param albumListVoPage 分页信息
	 * @return
	 */
	@Override
	public Page<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Long userId, Page<AlbumTrackListVo> albumListVoPage) {

		//获取专辑信息
		Page<AlbumTrackListVo> albumListVo = albumInfoMapper.selectFindAlbumTrackPage(albumId,albumListVoPage);
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		String payType = albumInfo.getPayType();

		List<AlbumTrackListVo> albumTrackListVos = albumListVo.getRecords();


		if(userId ==null){
			//用户未登录--且专辑是付费或者vip免费
			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType) || SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
				//返回免费可以观看的集数 其余的true
				albumTrackListVos.stream().filter(albumTrackListVo ->
						//过滤调免费的集数
						albumTrackListVo.getOrderNum() >albumInfo.getTracksForFree()
				).collect(Collectors.toList()).stream().forEach(albumTrackListVo -> {
					albumTrackListVo.setIsShowPaidMark(true);
				});
			}

		}else {
			//用户登录了
			//判断专辑是否免费
			if(SystemConstant.ALBUM_PAY_TYPE_FREE.equals(payType)){
				//专辑是免费的 全部是false
				return albumListVo ;

			}
			Boolean gouMaiFou = false;

			if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType)){
				//专辑是vip免费 验证用户vi
				//获取用户信息
				UserInfoVo userInfoVo = userFeignClient.getUserInfoVo(userId).getData();
				Assert.notNull(userInfoVo,"用户不存在");
				Integer isVip = userInfoVo.getIsVip();
				if(isVip.intValue()==0){
					//非会员 验证是否购买
					gouMaiFou =true;
				}
				if( isVip.intValue() ==1 && new Date().after(userInfoVo.getVipExpireTime()) ){
					//是会员但是过期了 验证购买否
					gouMaiFou =true;
				}
			}
			if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)){
				//专辑是付费的 查询用户是否购买
				gouMaiFou=true;
			}

			//获取需要验证的专辑id集合
			List<AlbumTrackListVo> albumTrackListVos1 = albumTrackListVos.stream().filter(albumTrackListVo ->
					albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());

			List<Long> needCheckTrackIdList = albumTrackListVos1.stream().map(albumTrackListVo ->
					albumTrackListVo.getTrackId()
			).collect(Collectors.toList());

			if(gouMaiFou){
				//判用户的购买专辑或者声音的情况
			Map<Long,Integer> map=userFeignClient.userIsPaidTrack(albumId,userId,needCheckTrackIdList).getData();

				albumTrackListVos1.stream().forEach(albumTrackListVo -> {
					if(map.get(albumTrackListVo.getTrackId()) ==0){
						//专辑是vip或者付费 却用户没有购买 限流！！！
						albumTrackListVo.setIsShowPaidMark(true);
					}
				});
			}

		}


		return albumListVo;
	}


	/**
	 * 提供给订单服务渲染购买商品（声音）列表-查询当前用户待购买声音列表
	 * @param trackId
	 * @param trackCount
	 * @return
	 */
	@Override
	public List<TrackInfo> getWaitBuyTrackInfoList(Long trackId, int trackCount) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//获取用户已经购买的声音
		List<Long> longList = userFeignClient.findUserPaidTrackList(trackInfo.getAlbumId()).getData();

		//select * from ablum_id =? and order_num>= ? notin(??) limit 20
		LambdaQueryWrapper<TrackInfo> trackInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
		trackInfoLambdaQueryWrapper.eq(TrackInfo::getAlbumId,trackInfo.getAlbumId());
		trackInfoLambdaQueryWrapper.ge(TrackInfo::getOrderNum,trackCount);
		trackInfoLambdaQueryWrapper.notIn(TrackInfo::getId ,longList);
		trackInfoLambdaQueryWrapper.last("limit "+trackCount);


		//获取用户正常需要购买的声音
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(trackInfoLambdaQueryWrapper);

		if (CollectionUtil.isEmpty(trackInfoList)) {
			throw new GuiguException(400, "该专辑下没有符合购买要求声音");
		}

		return trackInfoList;
	}

	private void saveAlbumStat(Long albumInfoId, String albumStatPlay, int i) {
		AlbumStat albumStat = new AlbumStat();
		albumStat.setAlbumId(albumInfoId);
		albumStat.setStatType(albumStatPlay);
		albumStat.setStatNum(i);
		albumStatMapper.insert(albumStat);
	}
}
